/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd.h"
#include "string.h"
#include "stdio.h"
#include "key.h"
#include "led.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//显示参数
#define LCD_PSD 0
#define LCD_STA 1
uint8_t Choose_display = LCD_PSD;
//占空比和频率
uint8_t Pulse = 50;
uint16_t Period = 2000;
//输入密码
uint8_t B1[11] = {'@','0','1','2','3','4','5','6','7','8','9'};
uint8_t B2[11] = {'@','0','1','2','3','4','5','6','7','8','9'};
uint8_t B3[11] = {'@','0','1','2','3','4','5','6','7','8','9'};
uint8_t Key_show_b1;
uint8_t Key_show_b2;
uint8_t Key_show_b3;
void LCD_Process(void)
{
	uint8_t lcd_buf[20];
	if(Choose_display == LCD_PSD)	//切换到输入密码界面
	{
		LCD_DisplayStringLine(Line1,(uint8_t *)"       PSD");
		
		sprintf((char *)lcd_buf,"    B1:%c",B1[Key_show_b1]);
		LCD_DisplayStringLine(Line3,lcd_buf);
		sprintf((char *)lcd_buf,"    B2:%c",B2[Key_show_b2]);
		LCD_DisplayStringLine(Line4,lcd_buf);
		sprintf((char *)lcd_buf,"    B3:%c",B3[Key_show_b3]);
		LCD_DisplayStringLine(Line5,lcd_buf);
	}
	
	if(Choose_display == LCD_STA)	//切换到输出界面
	{
		LCD_DisplayStringLine(Line1,(uint8_t *)"       STA");
		
		sprintf((char *)lcd_buf,"    F:%dHz",Period);
		LCD_DisplayStringLine(Line3,lcd_buf);
		sprintf((char *)lcd_buf,"    D:%d%%",Pulse);
		LCD_DisplayStringLine(Line4,lcd_buf);
	}
}

//PWM
uint8_t led_ctl = 0;
_Bool Check_First_ra;
uint32_t PWM_tick;
void PWM_Process(void)
{
	if (Choose_display == LCD_STA)	//输入密码正确
	{
		TIM2 -> ARR = 499;
		TIM2 -> CCR2 = 50;
		if (Check_First_ra == 0)	//输入密码正确后让tick相等一次，开始计时5s
		{
			PWM_tick = uwTick;
			Check_First_ra = 1;
		}
		if (uwTick - PWM_tick < 5000) return;
		Check_First_ra = 0;
		Choose_display = LCD_PSD;
		LCD_Clear(Black);
		Key_show_b1 = 0;Key_show_b2 = 0;Key_show_b3 = 0;
		led_ctl = led_ctl & (~0x01);
	}
	else				//输入密码错误
	{
		TIM2 -> ARR = 999;
		TIM2 -> CCR2 = 500;
	}
}

//检查输入密码是否正确
uint8_t password[3] = {'1','2','3'};
uint8_t Error_flag;
void Check_password(void)
{
	if(B1[Key_show_b1] == password[0] && B2[Key_show_b2] == password[1] && B3[Key_show_b3] == password[2])
	{
		Choose_display = LCD_STA;
		LCD_Clear(Black);
	}
	else
	{
		Error_flag ++;
		Choose_display = LCD_PSD;
		LCD_Clear(Black);
		Key_show_b1 = 0;Key_show_b2 = 0;Key_show_b3 = 0;
	}
}


//串口接收
uint8_t rx_buf[7];
uint8_t uart_buf[2];
uint8_t rx_count = 0;
uint32_t Rx_tick;
_Bool Check_Num;
void Rx_Process(void)
{
	if(uwTick - Rx_tick < 50) return;
	Rx_tick = uwTick;
	
	Check_Num = 0;
	
	if(Check_Num == 0 && rx_count > 0)
	{
		printf("Error\r\n");
	}
	
	rx_count = 0;
	memset(rx_buf,'\0',sizeof(rx_buf));
}

//检查串口输入字符是否正确,错误返回1，正确返回0
_Bool Check_string(void)
{
	if((rx_buf[0] == password[0]) && (rx_buf[1] == password[1]) && (rx_buf[2] == password[2]) && 
	   (rx_buf[3] == '-') && (rx_buf[4] >= '0') && (rx_buf[4] <= '9') && (rx_buf[5] >= '0') && 
	   (rx_buf[5] <= '9') && (rx_buf[6] >= '0') && (rx_buf[6] <= '9'))
		return 0;
	else
		return 1;	
}

//串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	Rx_tick = uwTick;
	rx_buf[rx_count ++] = uart_buf[0];
	HAL_UART_Receive_IT(&huart1,uart_buf,1);
	
	if(rx_count == 7)
	{
		rx_count = 0;
		Check_Num = 1;
		if(Check_string() == 0)
		{
			password[0] = rx_buf[4];
			password[1] = rx_buf[5];
			password[2] = rx_buf[6];
		}
		else
		{
			printf("Error\r\n");
		}
	}

} 

//按键
uint32_t Key_tick;
void Key_Process(void)
{
	if(uwTick - Key_tick < 20) return;
	Key_tick = uwTick;
	
	Key_Read();
	
	if(Choose_display == LCD_PSD)
	{
		if(Trg & 0x01)
		{
			Key_show_b1 ++;
			if(Key_show_b1 == 11)
			{
				Key_show_b1 = 1;
			}
		}
		if(Trg & 0x02)
		{
			Key_show_b2 ++;
			if(Key_show_b2 == 11)
			{
				Key_show_b2 = 1;
			}
		}
		if(Trg & 0x04)
		{
			Key_show_b3 ++;
			if(Key_show_b3 == 11)
			{
				Key_show_b3 = 1;
			}
		}
		if(Trg & 0x08)
		{
			Check_password();
		}	
	}
}

//LED
uint32_t LED_tick;
uint8_t LED_check_count;
void LED_Process(void)
{
	if(Choose_display == LCD_STA)
	{
		led_ctl |= 0x01;
	}
	else if(Error_flag >= 3)
	{
		if(uwTick - LED_tick < 100) return;
		LED_tick = uwTick;
		LED_check_count ++;
		if(LED_check_count == 50)
		{
			led_ctl = led_ctl & (~0x02);
			Error_flag = 0;
			LED_check_count = 0;
		}
		else
		{
			led_ctl = led_ctl ^ 0x02;
		}
	}
	else
	{
		LED_tick = uwTick;
	}
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1,uart_buf,1);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
    LCD_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

    LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);   
	
	LED_crl(0x00);
	
    while (1)
    {
    /* USER CODE END WHILE */
		LCD_Process();
		Key_Process();
		PWM_Process();
		Rx_Process();
		LED_Process();
		LED_crl(led_ctl);
    /* USER CODE BEGIN 3 */
    }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
